package com.shrfid.rfidsdk.tag;

import android.content.Context;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.os.Handler;
import android.util.Log;

import com.hoho.android.usbserial.driver.UsbId;
import com.hoho.android.usbserial.driver.UsbSerialDriver;
import com.hoho.android.usbserial.driver.UsbSerialProber;
import com.hoho.android.usbserial.util.SerialInputOutputManager;
import com.rfid.common.log.LogUtils;
import com.shrfid.module_base.entity.TagEntity;
import com.shrfid.module_base.util.ByteUtils;
import com.shrfid.rfidsdk.tag.base.BaseDecoder;
import com.shrfid.rfidsdk.tag.hf.HFCommand;
import com.shrfid.rfidsdk.tag.hf.HFDecoder;
import com.shrfid.rfidsdk.tag.uhf.UHFCommand;
import com.shrfid.rfidsdk.tag.uhf.UHFDecoder;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


/**
 * 标签读写控制类,用于书籍标签读取条码号或者硬件号,写入afi等功能
 */
public enum NewReadTagManager {

    INSTANCE;

    public static int INTERVAL_TIME = 1000;

    private final String TAG = "ReadTagDetectManager";

    private UsbSerialDriver sDriver;

    private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();

    public RfidDecoder rfidDecoder = new RfidDecoder();

    private SerialInputOutputManager mSerialIoManager;

    private BaseDecoder baseDecoder;

    private UsbManager mUsbManager;

    private UsbDevice device;

    private boolean isFindDevice = false;

    private IonDetectDeviceListener listener;

    private List<TagEntity> mTagEntities = new ArrayList<>();
    Handler handler = new Handler();

    //是否是超高频
    private boolean isUHF = false;

    private final SerialInputOutputManager.Listener mListener = new SerialInputOutputManager.Listener() {

        @Override
        public void onRunError(Exception e) {
            Log.d(TAG, "Runner stopped.");
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    startReadTag();
                }
            },3000);
        }

        @Override
        public void onNewData(final byte[] data) {
            if (baseDecoder != null) {
                baseDecoder.decode(data);
            }
        }
    };

    /**
     * 测试设备
     */
    private class FindDeviceThread extends Thread {
        @Override
        public void run() {
            super.run();
            System.out.println("UsbDevice device : mUsbManager.getDeviceList().values() size = " + mUsbManager.getDeviceList().values().size());
            for (final UsbDevice device : mUsbManager.getDeviceList().values()) {
                System.out.println( device.getProductName() + Integer.toHexString(device.getProductId()) + ":" +":" + Integer.toHexString(device.getVendorId()) +":" +  device.getDeviceName());
                //如果找到设备
                if (isFindDevice) {
                    break;
                }
                System.out.println(device.getProductName());
                if (device.getVendorId() == UsbId.VENDOR_PROLIFIC && device.getProductId() == UsbId.PROLIFIC_PL2303GT) {
                    final List<UsbSerialDriver> drivers = UsbSerialProber.probeSingleDevice(mUsbManager, device);
                    Log.d(TAG, "Found usb device: " + device);
                    if (!drivers.isEmpty()) {
                        final UsbSerialDriver usbSerialDriver = drivers.get(0);
                        try {
                            usbSerialDriver.open();
                            if (isUHF) {
                                usbSerialDriver.setParameters(115200, 8, UsbSerialDriver.STOPBITS_1, UsbSerialDriver.PARITY_NONE);
                            } else {
                                usbSerialDriver.setParameters(115200, 8, UsbSerialDriver.STOPBITS_1, UsbSerialDriver.PARITY_ODD);
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        stopIoManager();
                        mSerialIoManager = new SerialInputOutputManager(usbSerialDriver, mListener);
                        Log.i(TAG, "Starting io manager .." + mSerialIoManager);
                        mExecutor.submit(mSerialIoManager);
                        baseDecoder.setListener(new BaseDecoder.DecodeListener() {
                            @Override
                            public void onTagResult(List<TagEntity> data) {
                                LogUtils.v("onTagResult find device");
                                //到了这里说明有数据返回
                                isFindDevice = true;
//                                NewReadTagManager.this.sDriver = usbSerialDriver;
                                NewReadTagManager.this.device = device;
                            }
                        });
                        try {
                            //1秒后开始写入数据
                            Thread.sleep(1000);
                            //读取一次数据盘点
                            mSerialIoManager.writeAsync(baseDecoder.inventory());
                            //等待1秒
                            Thread.sleep(1000);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            LogUtils.v("find tag device : " + isFindDevice);
            close();
            listener.detectComplete();
        }
    }

    public void init(Context context, boolean isUHF, IonDetectDeviceListener listener) {
        this.listener = listener;
        this.isUHF = isUHF;
        mUsbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
        if (isUHF) {
            //超高频读写器
            baseDecoder = new UHFDecoder(new UHFCommand());
        } else {
            baseDecoder = new HFDecoder(new HFCommand());
        }
        new FindDeviceThread().start();
    }


    /**
     * 每次都重新打开，防止读不了的问题
     */
    public void startReadTag() {
        if (device != null) {
            final List<UsbSerialDriver> drivers = UsbSerialProber.probeSingleDevice(mUsbManager, device);
            if (!drivers.isEmpty()) {
                sDriver = drivers.get(0);
                try {
                    sDriver.open();
                    try {
                        if (isUHF) {
                            sDriver.setParameters(115200, 8, UsbSerialDriver.STOPBITS_1, UsbSerialDriver.PARITY_NONE);
                        } else {
                            sDriver.setParameters(115200, 8, UsbSerialDriver.STOPBITS_1, UsbSerialDriver.PARITY_ODD);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                startRead();
                setOnTagListener(new BaseDecoder.DecodeListener() {
                    @Override
                    public void onTagResult(List<TagEntity> data) {
                        mTagEntities.addAll(data);
                    }
                });
            } else {
                new FindDeviceThread().start();
            }
        } else {
            LogUtils.v("error! not found device");
            new FindDeviceThread().start();
        }
    }

    private void setOnTagListener(BaseDecoder.DecodeListener decodeListener) {
        if (baseDecoder != null) {
            baseDecoder.setListener(decodeListener);
        }
    }

    public void setReaderListener(BaseDecoder.ReaderListener readerListener) {
        if (baseDecoder != null) {
            baseDecoder.setReaderListener(readerListener);
        }
    }


    private void startRead() {
        stopIoManager();
        startIoManager();
    }

    private void stopIoManager() {
        if (mSerialIoManager != null) {
            Log.i(TAG, "Stopping io manager ..");
            mSerialIoManager.stop();
            mSerialIoManager = null;
        }
    }

    private void startIoManager() {
        if (sDriver != null) {
            mSerialIoManager = new SerialInputOutputManager(sDriver, mListener);
            Log.i(TAG, "Starting io manager .." + mSerialIoManager);
            mExecutor.submit(mSerialIoManager);
        }
    }


    /**
     * 同步读取标签,耗时操作
     *
     * @return 读取标签或者数据区数据
     */
    public List<TagEntity> readTags() {
        if (sDriver == null || mSerialIoManager == null) {
            startReadTag();
        }
        mTagEntities.clear();
        if (!isFindDevice) {
            return mTagEntities;
        }
        try {
            int result = sDriver.write(baseDecoder.inventory(), INTERVAL_TIME);
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return mTagEntities;
    }

    public void selectAntenna(int antenna) {
        try {
            if (sDriver == null || mSerialIoManager == null) {
                startReadTag();
            }
            int result = sDriver.write(baseDecoder.selectAntenna(antenna), INTERVAL_TIME);
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 打开书籍的标记位(感应门会报警)
     */
    public void openFlag(String uidStr, String afi) {
        if (sDriver == null) {
            return;
        }
        try {
            byte[] uid = ByteUtils.hexString2Bytes(uidStr);
            if (afi != null) {
                if (afi.startsWith("0x")) {
                    int iAfi = Integer.parseInt(afi.substring(2), 16);
                    sDriver.write(baseDecoder.writeAfi(uid, (byte) iAfi), INTERVAL_TIME);
                }
            } else {
                sDriver.write(baseDecoder.writeAfi(uid, (byte) 0x07), INTERVAL_TIME);
            }
            Thread.sleep(50);
            sDriver.write(baseDecoder.setEas(uid), INTERVAL_TIME);
            Thread.sleep(50);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 关闭书籍的标记位(感应不门会报警)
     */
    public void closeFlag(String uidStr) {
        if (sDriver == null) {
            return;
        }
        try {
            byte[] uid = ByteUtils.hexString2Bytes(uidStr);
            sDriver.write(baseDecoder.writeAfi(uid, (byte) 0xC2), INTERVAL_TIME);
            Thread.sleep(50);
            sDriver.write(baseDecoder.resetEas(uid), INTERVAL_TIME);
            Thread.sleep(50);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void close() {
        if (sDriver == null) {
            return;
        }
        try {
            stopIoManager();
            if (sDriver != null) {
                sDriver.close();
                sDriver = null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public interface IonDetectDeviceListener {
        void detectComplete();
    }

}